package com.feeyo.groundservice.composewidget.util

import androidx.compose.animation.core.LinearOutSlowInEasing
import androidx.compose.animation.core.animateDp
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.keyframes
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.Indication
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.offset
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableLongState
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

/**
 *作者：QLH on 2023-07-10
 *描述：
 */

/**
 * 防止重复点击(有的人可能会手抖连点两次,造成奇怪的bug)
 * @param intervalTime: 防止重复点击时间间隔
 * @param lastClickTime: 记录上次点击的时间
 * 特殊说明：如果是一组按钮则需要外部维护一个最后一次点击的值（一般切换时需要访问网络的这种）；如果是单按钮则不需要外部传值
 */
@Composable
inline fun Modifier.intervalClick(
    intervalTime: Int = 500,
    delayTime: Long = 0,
    lastClickTime: MutableLongState = remember { mutableLongStateOf(0) },
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    indication: Indication? = null,//LocalIndication.current,
    enabled: Boolean = true,
    onClickLabel: String? = null,
    role: Role? = null,
    crossinline onClick: () -> Unit
): Modifier {
    val coroutineScope = rememberCoroutineScope()
    return clickable(interactionSource, indication, enabled, onClickLabel, role) {
        val currentTimeMillis = System.currentTimeMillis()
        if (currentTimeMillis - intervalTime >= lastClickTime.longValue) {
            coroutineScope.launch {
                lastClickTime.longValue = currentTimeMillis
                delay(delayTime)
                onClick()
            }

        }
    }
}

/**
 * remember一个lambda
 */
@Composable
inline fun <T : Function<*>?> rel(lambda: T): T = remember { lambda }

/**
 * 获取居中的值
 */
internal fun midOf(min: Int, number: Int, max: Int): Int = maxOf(min, minOf(number, max))
internal fun midOf(min: Float, number: Float, max: Float): Float = maxOf(min, minOf(number, max))

/**
 * 根据this的百分比(0-1或1-0)来计算start到end对应的值,并返回
 */
internal fun Float/*percentage*/.getPercentageValue(startValue: Float, endValue: Float): Float =
    if (startValue == endValue) startValue
    else (endValue - startValue) * this + startValue

internal fun Float/*percentage*/.getPercentageValue(startValue: Color, endValue: Color): Color =
    Color(
        alpha = getPercentageValue(startValue.alpha, endValue.alpha),
        red = getPercentageValue(startValue.red, endValue.red),
        green = getPercentageValue(startValue.green, endValue.green),
        blue = getPercentageValue(startValue.blue, endValue.blue),
    )


fun Modifier.horizonShake(
    change: MutableState<Boolean>,
    intensity: Dp = 15.dp,//震动幅度
    durationMillis: Int = 500, //动画时间
    delayMillis: Int = 0 //延迟执行
) = composed {
    val transition = updateTransition(change)

    //相对位置
    val position = listOf(0f, -1f, 1f, -0.8f, 0.8f, -0.6f, 0.6f, -0.2f, 0.2f, 0f)
    val density = LocalDensity.current
    val pxIntensity = with(density) { intensity.toPx() }
    val frameCount = position.size
    val frameDuration = durationMillis / (frameCount - 1).coerceAtLeast(1)


    val keyframesSpec = keyframes<Float> {
        this.durationMillis = durationMillis
        this.delayMillis = delayMillis
        position.forEachIndexed { index, ratio ->
            (pxIntensity * ratio) at (index * frameDuration)
        }
    }
    val shakeOffset by transition.animateFloat(
        transitionSpec = {
            keyframesSpec
        }, label = "shakeOffset", targetValueByState = {
            if (it.value)
                1f
            else
                0f
        })

    offset(x = shakeOffset.pxToDp())
}

fun Modifier.verticalShake(
    change: MutableState<Boolean>,
    intensity: Dp = 15.dp,//震动幅度
    durationMillis: Int = 500, //动画时间
    delayMillis: Int = 0 //延迟执行
) = composed {
    val transition = updateTransition(change)

    //相对位置
    val position = listOf(0f, -1f, 1f, -0.8f, 0.8f, -0.6f, 0.6f, -0.2f, 0.2f, 0f)
    val density = LocalDensity.current
    val pxIntensity = with(density) { intensity.toPx() }
    val frameCount = position.size
    val frameDuration = durationMillis / (frameCount - 1).coerceAtLeast(1)


    val keyframesSpec = keyframes<Float> {
        this.durationMillis = durationMillis
        this.delayMillis = delayMillis
        position.forEachIndexed { index, ratio ->
            (pxIntensity * ratio) at (index * frameDuration)
        }
    }
    val shakeOffset by transition.animateFloat(
        transitionSpec = {
            keyframesSpec
        }, label = "shakeOffset", targetValueByState = {
            if (it.value)
                1f
            else
                0f
        })

    offset(y = shakeOffset.pxToDp())
}